Skip to content

feat(FR-2907): add matte + natural-size cap for doc images, tighten capture guidance#7453

Open
yomybaby wants to merge 2 commits into
mainfrom
feat-fr-2907-doc-image-matte-and-size-cap
Open

feat(FR-2907): add matte + natural-size cap for doc images, tighten capture guidance#7453
yomybaby wants to merge 2 commits into
mainfrom
feat-fr-2907-doc-image-matte-and-size-cap

Conversation

@yomybaby
Copy link
Copy Markdown
Member

@yomybaby yomybaby commented May 17, 2026

Resolves #7451(FR-2907)

Why

Three recurring visual issues with documentation screenshots, all visible on the Korean sessions_all page:

  1. Cramped element-level captures — Playwright browser_take_screenshot with a ref produces PNGs whose content is flush against every edge. Example: session_type_batch.png (2669×1770) — text and the wizard step indicator are touching the image borders.
  2. Border-radius mismatch on single-card / single-modal captures — the inner card's own rounded corners visibly clash with the .doc-image wrapper's outer radius. Example: launch_session_confirm.png.
  3. Tiny captures stretched to full content width — the web pipeline did not auto-scale images by their captured pixel dimensions, so a 760×190 notification got blown up to fill the article column. Example: session_notification.png. PDF already auto-scaled via IMAGE_SCALE_FACTOR = 0.5; web did not.

What changes

Renderer (`packages/backend.ai-docs-toolkit`)

  • `markdown-processor-web.ts` — mirror the PDF auto-size logic. When no explicit `alt =<w>` size hint is present, read the PNG header via the (now-exported) `getImageDimensions()` helper and emit `style="max-width: ${dims.width / 2}px"`. The `× 0.5` factor undoes the 2× zoom capture convention from `SCREENSHOT-GUIDELINES.md`, so a 760-pixel-wide notification renders at ~380 CSS px — its intended size — instead of the full article column. The disk-path resolver also rejects paths that escape `//` via `..` segments (defense in depth, post-review).
  • `styles-web.ts` / `styles.ts` — move border / radius / shadow from `.doc-image` (the ``) to `figure.doc-figure` (the wrapper). Add padding + a subtly off-white background (`--bai-bg-muted` on web, `#fafafa` in PDF) so the wrapper acts as a matte / frame. The figure uses `width: fit-content; max-width: 100%` with `margin: ... auto` so the matte hugs the (possibly auto-capped) image instead of spanning the full article column.
    Effects:
    • Element-level captures with content flush to the PNG edges now have visible breathing room — without any recapture.
    • Cards/modals with their own rounded corners sit cleanly on the matte; the matte's radius is the only outer radius, so the previous nested-radius clash is gone.
    • Small images (e.g. a 380-px-wide notification) are wrapped in a 412-px matte, not a 700-px column-wide one.
  • `markdown-processor.ts` — export `getImageDimensions` and `IMAGE_SCALE_FACTOR` so the web renderer can reuse the PDF-side helpers without re-implementing the PNG/JPEG header parser. The scale factor now has an explanatory docstring tying it back to the 2× zoom capture convention.

Capture guidance (`packages/backend.ai-webui-docs/SCREENSHOT-GUIDELINES.md`)

New "Padding & Framing" section that documents:

  • Renderer-side auto size cap — authors do not need to size most images manually; the renderer reads the PNG dimensions and caps at `pixel_width × 0.5`.
  • Parent-container-preferred rule — when in doubt about which element to capture, climb one DOM level (`.ant-modal-wrap` over `.ant-modal`, etc.) so the capture picks up the application's intra-component spacing.
  • Small-element rule (≤ 600 CSS px) — for tiny widgets (notifications, badges, button rows), either trust the auto cap or reposition the element with `browser_evaluate` for a larger deliberate capture. Snippet provided.
  • Inner-vs-outer radius behavior — authors should NOT try to fix radius mismatches at capture time; the matte handles it.

The existing "Match the Existing Screenshot's Framing" table is updated to reference the new rules.

Capture agent (`.claude/agents/docs-screenshot-capturer.md`)

Prompt updates to match the new guidance: capture raw elements and let the matte frame them, prefer parent containers, handle small widgets via the auto cap (default) or `browser_evaluate` repositioning (when more screen real estate is needed).

Verification

  • `pnpm --filter backend.ai-docs-toolkit build` — passes (TypeScript clean).
  • `pnpm --filter backend.ai-docs-toolkit test` — 231 / 232 pass (1 pre-existing skip).
  • `node ../backend.ai-docs-toolkit/dist/cli.js build:web --lang ko` from `packages/backend.ai-webui-docs/` — generated HTML for the three problem images now carries the expected inline `max-width`:
    • `session_type_batch.png` (2669×1770) → `max-width:1335px`
    • `launch_session_confirm.png` (1400×1624) → `max-width:700px`
    • `session_notification.png` (760×190) → `max-width:380px`
  • Headless Chrome render of `sessions_all.html` confirms the matte is visible around each figure and the notification no longer fills the column. After the post-review shrink-to-fit fix, the notification matte measures 414×163 (380-px image + 16-px padding × 2) instead of the earlier column-wide 616×163.
  • `bash scripts/verify.sh` — Relay / Lint / Format / Vite paths pass. (TypeScript step shows pre-existing errors on `main` unrelated to this PR — confirmed on `HEAD~1`.)

Follow-up

  • FR-2908 ("intent-based alt text + figcaption separation") is intentionally separated. The two issues touch overlapping files (`markdown-processor*.ts`, `SCREENSHOT-GUIDELINES.md`, `docs-screenshot-capturer.md`), so FR-2908 is sequenced on top of this PR.

Checklist:

  • Documentation (`SCREENSHOT-GUIDELINES.md`, agent prompt)
  • Minimum required manager version — N/A (frontend-only docs toolkit change)
  • Specific setting for review — load any localized docs page (e.g. `sessions_all`) and confirm screenshots render inside a soft off-white matte with visible padding, and that the small notification figure is no longer column-width.
  • Minimum requirements to check during review — figures in 4 languages render identically (matte + size cap are language-independent).
  • Test case(s) to demonstrate the difference — visual; see the three image URLs above for the before state.

…apture guidance

- markdown-processor-web.ts: emit max-width=(pixel_width × 0.5) from PNG
  header so 2× zoom captures display at intended CSS size. Mirrors the
  PDF auto-scale logic. Explicit ![alt =<w>](url) size hints still win.
- styles-web.ts / styles.ts: move border/radius/shadow from .doc-image
  (img) to figure.doc-figure (wrapper); add padding + neutral background
  so the wrapper acts as a matte. Element-level captures with content
  flush to the PNG edges now have visible breathing room without any
  recapture. Cards/modals with their own rounded corners no longer
  compete with a second outer radius.
- markdown-processor.ts: export getImageDimensions + IMAGE_SCALE_FACTOR
  so the web renderer can reuse the PDF dimension/scale helpers.
- SCREENSHOT-GUIDELINES.md: document the matte, the renderer-side
  auto size cap, the parent-container-preferred rule, and the
  small-element rule (≤ 600 CSS px).
- docs-screenshot-capturer.md: prompt update — capture raw elements
  and let the matte frame them, prefer parent containers, handle
  small widgets via auto-cap or browser_evaluate repositioning.
@github-actions github-actions Bot added the size:L 100~500 LoC label May 17, 2026
Copy link
Copy Markdown
Member Author


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • flow:merge-queue - adds this PR to the back of the merge queue
  • flow:hotfix - for urgent changes, fast-track this PR to the front of the merge queue

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has required the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@yomybaby yomybaby marked this pull request as ready for review May 17, 2026 23:13
Copilot AI review requested due to automatic review settings May 17, 2026 23:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Backend.AI documentation toolkit and screenshot authoring guidance to support matte-framed documentation images and automatic natural-size display caps for captured screenshots.

Changes:

  • Adds matte-style image framing for web and PDF documentation output.
  • Exports shared image dimension/scale helpers and applies automatic web image max-width caps.
  • Updates screenshot capture guidance for modal framing, small widgets, and renderer-side sizing behavior.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/backend.ai-webui-docs/SCREENSHOT-GUIDELINES.md Adds authoring guidance for matte framing, parent-container captures, and small-element sizing.
packages/backend.ai-docs-toolkit/src/styles.ts Updates PDF image figure styling to use a matte frame.
packages/backend.ai-docs-toolkit/src/styles-web.ts Updates web image figure styling to use a matte frame and bare inner images.
packages/backend.ai-docs-toolkit/src/markdown-processor.ts Exports shared image dimension and image scale helpers.
packages/backend.ai-docs-toolkit/src/markdown-processor-web.ts Adds web-side image dimension lookup and automatic max-width sizing.
.claude/agents/docs-screenshot-capturer.md Updates screenshot capture agent guidance to align with the matte and sizing behavior.

Comment thread packages/backend.ai-docs-toolkit/src/markdown-processor-web.ts Outdated
Comment thread packages/backend.ai-docs-toolkit/src/styles-web.ts
Comment thread packages/backend.ai-docs-toolkit/src/styles.ts
…er against traversal

Copilot review on #7453:
- styles-web.ts / styles.ts: `figure.doc-figure` was a default block, so
  the matte spanned the full article column even when the inner <img>
  was capped (e.g. a 760-px notification was rendered at 380 px inside
  a column-wide matte). Add `width: fit-content; max-width: 100%` so
  the matte shrinks to the largest child (capped image or caption),
  with `margin: ... auto` keeping it centered.
- markdown-processor-web.ts: `resolveWebImageDiskPath` only checked
  that the href started with '/' before joining it under <srcDir>/<lang>.
  A '/../other-lang/foo.png' would slip past and let the renderer read
  PNG headers outside the language root just to compute display
  dimensions. `rewriteImagePathsForWeb` already filters out-of-tree
  refs, but enforce the same boundary at the resolver too (defense in
  depth).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100~500 LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: add matte + natural-size cap for doc images, tighten capture guidance

2 participants